let inputElement = document.getElementsByTagName('input')[0];
let resolveBtn = document.getElementsByClassName('btn')[0];
let beginTime = 0;
let downloadCount = 0;
let resolveCount = 0;
// 视频的前缀,只需要修改 .../video/av?p= 中的 av 号即可
let prefix = "https://www.bilibili.com/video/BV1EN411X7jw/?p=";
// 从点击完解析按钮到解析完成的时间间隔，默认1s
let interval = 2000;
// 从第几集开始下载，默认是从第一集开始
let beginPart = 1;
// 要下载的视频的集数
let num = 13;
// 算出最后一个Part
let endPart = beginPart + num - 1;
// 标记每一Part是否需要重置，1表示需要,0表示不需要
let retryCandidate = new Array(num);
retryCandidate.fill(1);
let retryTime = (interval + 1000) * num;


// 下载视频,url:视频链接,name:下载后的文件名
function downloadVideo(url,name) {
   //创建XMLHttpRequest对象
   let httpRequest = new XMLHttpRequest();
   //打开连接，将请求参数拼在url后面
   httpRequest.open('GET', url, true);
   //设置期望的返回值类型
   httpRequest.responseType = "blob";
   //请求成功回调函数
   httpRequest.onload = function (oEvent) {
       if (httpRequest.status === 200) {
          let fileName = decodeURI(name+'.mp4');
          let response = httpRequest.response;
          //数据转换为文件下载
          let elink = document.createElement('a');
          elink.download = fileName;
          elink.style.display = 'none';
          let blob = new Blob([response]);
          elink.href = URL.createObjectURL(blob);
          document.body.appendChild(elink);
          elink.click();
          document.body.removeChild(elink);
          console.log('视频' + fileName + '下载完成');
          downloadCount = downloadCount + 1;
          console.log('下载进度' + downloadCount + '/' + num);

       }else {
          console.log('下载失败,请手动下载,视频url ' + url);
       }
   }

   httpRequest.send();
   
};

// 解析Part的url与名称
function resolve(i) {
   if (document.getElementsByClassName('caption').length > 0) {
      // 获取解析后的url
      let url = document.getElementsByClassName('caption')[0].getElementsByTagName('p')[1].getElementsByTagName('a')[0].getAttribute('href');
      // 获取文件名
      let name = document.getElementsByClassName('caption')[0].getElementsByTagName('p')[0].innerText;
      // 为了保证下载后的视频顺序，统一加上'Part-'前缀
      name = 'Part-' + i + ' ' + name;
      resolveCount = resolveCount + 1;
      // 这里-1的目的是为了将逻辑下标变成物理下标
      retryCandidate[i-1] = 0;
      downloadVideo(url, name);
   } else {
      console.log('第' + i + '集视频解析失败,稍后将会重试');
   }
   console.log('解析进度：' + resolveCount + '/' + num);
};

// 调用网页的解析功能
function sendResolvRequest(i) {
   console.log('当前正在解析第' + i + '集视频');
   // url
   let bilibiliUrl = prefix + i;
   inputElement.value = bilibiliUrl;
   let evt = document.createEvent('HTMLEvents');
   evt.initEvent('input',true,true);
   inputElement.dispatchEvent(evt);
   // 触发按钮点击事件
   resolveBtn.click();
   // 解析结果
   setTimeout(resolve(i),interval);
};

function doRetry() {
   console.log('开始重试');
   // 待重试的数量
   let len = num - resolveCount;
   // 重置开始解析的时间,初始化为0，表示第一次解析是在0s后执行，也就是立刻执行
   beginTime = 0;
   console.log('剩余解析失败的视频数量:',len);
   // 遍历retryCandidate数组，找出需要重试的part
   for(let i = 0; i < num; i++) {
      if (retryCandidate[i] == 1) {
         setTimeout(function(){
            // 物理下标转逻辑下标
            sendResolvRequest(i+1);
         },beginTime);
         console.log('第' + (i + 1) + '个视频将在' + beginTime/1000 + '秒后重试');
         beginTime = beginTime + interval + 1000;
      }
   }
   // 计算下一次重试的开始时间
   let retryTime = (interval + 1000) * len ;
   console.log('将在' + retryTime/1000 + 's后进行下一轮重试');
   setTimeout(function() {
      retry();
   },retryTime);
}

// 重试失败的Part
function retry() {
   // 成功解析的Part的数量 < 预期解析的Part的数量
   if (resolveCount < num) {
      console .log('开始重试');
      doRetry()
   }
}

// 正常的去解析下载每一个Part
for(let i = beginPart; i <= endPart; i++) {
   setTimeout(function(){
      sendResolvRequest(i);
   },beginTime);
   beginTime = beginTime + interval + 1000;
}

// 在上面循环结束完之后会解析重试失败的Part
setTimeout(function() {
   retry();
},retryTime);